본문으로 건너뛰기

프로세스 동기화

동기화란

  • 협력하여 실행되는 프로세스들은 실행 순서자원의 일관성을 보장해야 하기에 반드시 동기화 되어야 한다.
  • 동기화: 특정 자원에 접근할 때 한 개의 프로세스만 접근(상호배제)하게 하거나, 프로세스를 올바른 순서대로 실행하게 하는 것(실행 순서 제어)을 의미
  • 공유 자원: 여러 프로세스들이 같이 사용하는 자원들(ex. 전역 변수, 파일, 입출력장치, 보조기억장치 등등)
  • 임계 구역: 동시에 실행하면 문제가 발생하는 자원에 접근하는 코드 영역
  • 레이스 컨디션: 잘못된 실행으로 인해 여러 프로세스가 동시 다발적으로 임계 구역의 코드를 실행하여 문제가 발생하는 경우

: 여러 줄의 저급 언어로 변환된 고급 언어 한줄을 실행하는 과정에서 문맥 교환이 일어날 수 있다. 저급 언어를 실행하는 과정에서 문맥 교환이 일어날 때 문제가 발생할 수 있게 된다.

  • 운영체제는 임계 구역 문제를 세 가지 원칙 하에 해결한다.
    • 상호 배제: 한 프로세스가 임계 구역에 진입했다면 다른 프로세스는 임계 구역에 들어올 수 없다.
    • 진행: 임계 구역에 어떤 프로세스도 진입하지 않았다면 임계 구역에 진입하고자 하는 프로세스는 들어갈 수 있어야 한다.
    • 유한 대기: 한 프로세스가 임계 구역에 진입하고 싶다면 그 프로세스는 언젠가는 임계 구역에 들어올 수 있어야 한다. (임계 구역에 들어오기 위해 무한정 대기해서는 안됨!)

동기화 기법

  1. 뮤텍스 락: 동시에 접근해서는 안되는 자원에 동시 접근하지 않도록 만드는 도구

    → 상호 배제를 위한 동기화 도구

    → 하나의 공유 자원에 접근하는 프로세스를 상정한 방식

    방법)

    • 프로세스들이 공유하는 전역 변수 lock
    • acquire 함수(임계 구역 잠금)
    • release 함수(임계 구역 잠금 해제)
    // acquire
    acquire() {
    	while (lock == true) // 만약 임계 구역이 잠겨 있다면
    		;                  // 임계 구역이 잠겨 있는지 반복하여 확인
    	lock = true;         // 임계 구역이 잠겨 있지 않다면 임계 구역 잠금
    }
    
    // release
    release() {
    	lock = false; // 임계 구역 작업이 끝났으니 잠금 해제
    }
    
    acquire();
    // 임계 구역
    release();
    
    1. lock을 획득할 수 없다면(임계 구역에 진입할 수 없다면) 무작정 기다린다. → 계속 반복하며 확인해보는 busy wait(바쁜 대기) 현상 발생
    2. lock을 획득할 수 있다면(임계 구역에 진입할 수 있다면) 임계 구역을 잠근 뒤 임계 구역에서의 작업을 진행한다.
    3. 임계 구역에서 빠져나올 때엔 다시 임계 구역의 잠금을 해제한다.
  2. 세마포: 공유 자원이 여러개 있는 임계 구역 문제도 해결할 수 있는 동기화 도구

    → 공유 자원이 여러개 있는 상황에서도 적용이 가능한 동기화 도구

    방법1)

    • 임계 구역에 진입할 수 있는 프로세스의 개수를 나타내는 전역변수 S
    • 임계 구역에 들어가도 좋은지 혹은 기다려야 할 지 알려주는 wait 함수
    • 임계 구역 앞에서 기다리는 프로세스에 이제 가도 좋다고 신호를 주는 signal 함수
    // wait
    wait() {
    	while (s <= 0) // 만일 임계 구역에 진입할 수 있는 프로세스 개수가 0 이하라면
    	;              // 사용할 수 있는 자원이 있는지 반복적으로 확인하고
    	s--;           // 임계 구역에 진입할 수 있는 프로세스 개수가 하나 이상이면 s를 1감소시키고 임계 구역 진입
    }
    
    // signal
    signal() {
    	s++;  // 임계 구역에서의 작업을 마친 뒤 s를 1증가
    }
    
    wait();
    // 임계 구역
    signal();
    

    방법1도 뮤텍스 락과 마찬가지로 busy wait 현상 발생 → cpu 낭비!

    방법2) 방법1에서 busy wait 현상 안생기게 해줌

    • 임계 구역에 진입할 수 있는 프로세스의 개수를 나타내는 전역변수 S
    • 사용할 수 있는 자원이 없을 경우 해당 프로세스 상태를 대기 상태로 만들고 그 프로세스의 PCB를 세마포를 위한 대기 큐에 집어넣는 wait 함수
    • 대기 중인 프로세스가 있다면 해당 프로세스를 대기 큐에서 제거하고, 프로세스 상태를 준비 상태로 변경한 귀 준비 큐로 옮겨주는 signal 함수
    // wait
    wait() {
    	s--;
    	if (s < 0) {
    		add this process to Queue; // 해당 프로세스 PCB를 대기 큐에 삽입
    		sleep();                   // 대기 상태로 접어듬
    	}
    }
    
    // signal
    signal() {
    	s++;
    	if (s >= 0) {
    		remove a process p from Queue // 대기 큐에 있는 프로세스 p 제거
    		wakeup(p)                     // 프로세스 p를 대기 상태에서 준비 상태로 만들기
    	}
    }
    

    실행 순서 제어를 위한 동기화 도구로 사용하는 방법)

    • 세마포의 변수 S를 0으로 두고
    • 먼저 실행할 프로세스 뒤에 signal 함수를,
    • 다음에 실행할 프로세스 앞에 wait 함수 붙이기

    → 어떤 프로세스가 먼저 실행하든 내가 원하는 순서로 실행됨

    세마포의 단점: 매번 임계 구역의 앞뒤로 일일이 wait과 signal 함수를 명시해야 하는 번거로움이 있다.

  3. 모니터: 공유 자원을 다루는 인터페이스에 접근하기 위한 큐(모니터에 진입하기 위한 큐)를 만들고 모니터 안에 항상 하나의 프로세스만 들어오도록 하여 상호 배제를 위한 동기화를 제공

    → 세마포에 비해 사용자가 사용하기 편리함




    → 실행 순서를 위한 동기화도 제공(특정 조건을 바탕으로 프로세스를 실행하고 일시 중단하기 위해 조건 변수를 사용)

    조건 변수1) wait

    • 호출한 프로세스의 상태를 대기 상태로 전환하고 일시적으로 조건 변수에 대한 대기 큐에 삽입하는 연산
    • 모니터에 이미 진입한 프로세스의 실행 조건이 만족될 때까지 잠시 실행이 중단되어 기다리기 위해 만들어진 큐
    • 특정 프로세스가 아직 실행될 조건이 되지 않았을 때 wait을 통해 실행 중단

    조건 변수2) signal

    • wait을 호출하여 큐에 삽입된 프로세스의 실행을 재개하는 연산
    • 특정 프로세스가 실행될 조건이 충족되었을 때 signal을 통해 실행 재개